package com.example.demo.services.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.port.fee.dao.FeeRecordMapper;
import com.port.fee.entity.Cargo;
import com.port.fee.entity.FeeRecord;
import com.port.fee.entity.FeeType;
import com.port.fee.service.CargoService;
import com.port.fee.service.FeeRecordService;
import com.port.fee.service.FeeTypeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 费用记录服务实现
 */
@Service
public class FeeRecordServiceImpl extends ServiceImpl<FeeRecordMapper, FeeRecord> implements FeeRecordService {

    private static final Logger LOGGER = LoggerFactory.getLogger(FeeRecordServiceImpl.class);

    @Autowired
    private CargoService cargoService;

    @Autowired
    private FeeTypeService feeTypeService;

    @Override
    public FeeRecord getFeeRecordById(Long feeId) {
        return getById(feeId);
    }

    @Override
    public Page<FeeRecord> listFeeRecords(FeeRecord feeRecord, int pageNum, int pageSize) {
        LambdaQueryWrapper<FeeRecord> queryWrapper = new LambdaQueryWrapper<>();

        // 根据货物ID查询
        if (feeRecord.getCargoId() != null) {
            queryWrapper.eq(FeeRecord::getCargoId, feeRecord.getCargoId());
        }

        // 根据客户ID查询
        if (feeRecord.getCustomerId() != null) {
            queryWrapper.eq(FeeRecord::getCustomerId, feeRecord.getCustomerId());
        }

        // 根据费用类型ID查询
        if (feeRecord.getFeeTypeId() != null) {
            queryWrapper.eq(FeeRecord::getFeeTypeId, feeRecord.getFeeTypeId());
        }

        // 根据支付状态查询
        if (feeRecord.getPayStatus() != null) {
            queryWrapper.eq(FeeRecord::getPayStatus, feeRecord.getPayStatus());
        }

        // 按创建时间降序排序
        queryWrapper.orderByDesc(FeeRecord::getCreateTime);

        return page(new Page<>(pageNum, pageSize), queryWrapper);
    }

    @Override
    public FeeRecord calculateFee(Long cargoId, Date calcEndDate) {
        LOGGER.info("计算费用, cargoId={}, calcEndDate={}", cargoId, calcEndDate);

        // 获取货物信息
        Cargo cargo = cargoService.getCargoById(cargoId);
        if (cargo == null) {
            LOGGER.error("计算费用失败: 货物不存在, cargoId={}", cargoId);
            return null;
        }

        // 确定计算截止日期
        Date endDate = calcEndDate;
        if (endDate == null) {
            if (cargo.getExitTime() != null) {
                // 如果货物已出港，使用出港时间
                endDate = cargo.getExitTime();
            } else {
                // 否则使用当前时间
                endDate = new Date();
            }
        }

        // 获取货物进港时间
        Date startDate = cargo.getEntryTime();
        if (startDate == null) {
            LOGGER.error("计算费用失败: 货物进港时间为空, cargoId={}", cargoId);
            return null;
        }

        // 获取存储天数
        long diffInMillies = Math.abs(endDate.getTime() - startDate.getTime());
        long diffDays = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
        int storageDays = (int) diffDays;
        if (diffInMillies % TimeUnit.DAYS.toMillis(1) > 0) {
            // 如果有不足一天的，按一天计算
            storageDays++;
        }

        LOGGER.info("计算费用: 货物={}, 计费日期={} 至 {}, 堆存天数={}",
                cargo.getCargoName(), startDate, endDate, storageDays);

        // 根据货物类型获取费用类型
        String feeCode;
        switch (cargo.getCargoType()) {
            case "危险品":
                feeCode = "STORAGE_DANGEROUS";
                break;
            case "冷藏货物":
                feeCode = "STORAGE_REFRIGERATED";
                break;
            default:
                feeCode = "STORAGE_NORMAL";
                break;
        }

        LOGGER.info("获取费用类型, 货物类型={}, 费用编码={}", cargo.getCargoType(), feeCode);

        // 获取费用类型信息
        FeeType feeType = feeTypeService.getFeeTypeByCode(feeCode);
        if (feeType == null) {
            LOGGER.error("计算费用失败: 费用类型不存在, feeCode={}", feeCode);
            return null;
        }

        // 计算免费天数
        int freeDays = feeType.getFreeDays() != null ? feeType.getFreeDays() : 0;

        // 计算计费天数
        int chargeableDays = Math.max(0, storageDays - freeDays);

        // 计算费用
        BigDecimal unitPrice = feeType.getUnitPrice();
        BigDecimal quantity = cargo.getQuantity();
        BigDecimal amount = unitPrice.multiply(quantity).multiply(new BigDecimal(chargeableDays))
                .setScale(2, RoundingMode.HALF_UP);

        LOGGER.info("费用计算结果: 单价={}, 数量={}, 计费天数={}, 金额={}",
                unitPrice, quantity, chargeableDays, amount);

        // 封装费用记录
        FeeRecord feeRecord = new FeeRecord();
        feeRecord.setCargoId(cargoId);
        feeRecord.setCustomerId(cargo.getCustomerId());
        feeRecord.setFeeTypeId(feeType.getFeeTypeId());
        feeRecord.setStartDate(startDate);
        feeRecord.setEndDate(endDate);
        feeRecord.setStorageDays(storageDays);
        feeRecord.setFreeDays(freeDays);
        feeRecord.setChargeableDays(chargeableDays);
        feeRecord.setQuantity(quantity);
        feeRecord.setUnitPrice(unitPrice);
        feeRecord.setAmount(amount);
        feeRecord.setCurrency(feeType.getCurrency());
        feeRecord.setPayStatus(0); // 未支付
        feeRecord.setCreateTime(new Date());
        feeRecord.setUpdateTime(new Date());

        return feeRecord;
    }

    @Override
    public boolean addFeeRecord(FeeRecord feeRecord) {
        // 设置默认值
        if (feeRecord.getPayStatus() == null) {
            feeRecord.setPayStatus(0); // 默认未支付
        }

        if (feeRecord.getCurrency() == null) {
            feeRecord.setCurrency("CNY"); // 默认人民币
        }

        feeRecord.setCreateTime(new Date());
        feeRecord.setUpdateTime(new Date());

        return save(feeRecord);
    }

    @Override
    public boolean updateFeeRecord(FeeRecord feeRecord) {
        feeRecord.setUpdateTime(new Date());
        return updateById(feeRecord);
    }

    @Override
    public boolean confirmPayment(Long feeId) {
        FeeRecord feeRecord = getById(feeId);
        if (feeRecord == null) {
            LOGGER.error("确认支付失败: 费用记录不存在, feeId={}", feeId);
            return false;
        }

        feeRecord.setPayStatus(1); // 已支付
        feeRecord.setUpdateTime(new Date());

        return updateById(feeRecord);
    }

    @Override
    public BigDecimal getTotalFeeByCargoId(Long cargoId) {
        return baseMapper.getTotalFeeByCargoId(cargoId);
    }

    @Override
    public List<Map<String, Object>> statisticsByFeeType() {
        return baseMapper.statisticsByFeeType();
    }

    @Override
    public List<Map<String, Object>> statisticsByCustomer() {
        return baseMapper.statisticsByCustomer();
    }
}